package top.dreamix.njitkit.ui.screen

import android.Manifest
import android.content.Context
import android.content.Intent
import android.net.ConnectivityManager
import androidx.annotation.RequiresPermission
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import cafe.adriel.lyricist.LocalStrings
import top.dreamix.njitkit.data.network.Account
import top.dreamix.njitkit.data.network.NetworkSetting
import top.dreamix.njitkit.data.network.Operator
import top.dreamix.njitkit.ui.viewmodel.NetworkConfigUiState
import top.dreamix.njitkit.util.Log
import top.dreamix.njitkit.util.NetworkUtil

@Composable
fun CaptivePortalLoginUi(
    uiState: NetworkConfigUiState,
    finishActivity: () -> Unit = {},
    ignoreNetwork: () -> Unit = {},
    confirmNetwork: () -> Unit = {},
    saveNetworkSetting: (NetworkSetting) -> Unit = {},
    loginNetwork: (Account, callback: (Boolean, String) -> Unit) -> Unit = { _, _ ->},
    intent: Intent = Intent(),
    onAccountSelected: (String) -> Unit = { _ ->}
) {
    val strings = LocalStrings.current
    val context = LocalContext.current
    var dialogToShow by remember { mutableStateOf("loading") }
    var message by remember { mutableStateOf("") }

    var portalState by remember { mutableStateOf(-1) }

    LaunchedEffect(Unit) {
        portalState = NetworkUtil.getPortalState()
    }
    LaunchedEffect(portalState) {
        when(portalState) {
            -1 -> {}
            0 -> {
                Log.info("Calling confirmNetwork because portal ok")
                confirmNetwork()
                finishActivity()
//                dialogToShow = "message"
//                message = strings.portalAuthenticated
            }
            1 ->
                if (uiState.networkSetting.autoLogin && uiState.networkSetting.defaultAccountId != null)
                    uiState.allAccounts.find { it.id == uiState.networkSetting.defaultAccountId }?.let {
                        // display Loading dialog
                        dialogToShow = "loading"
                        loginNetwork(it) { success, msg ->
                            if (success) {
                                confirmNetwork()
                                finishActivity()
                            }
                            message = msg
                            dialogToShow = "message"
                        }
                    } else {
                    dialogToShow = "login"
                }
            2 ->
                dialogToShow = "unsupported"
        }
    }


    when (dialogToShow) {
        "login" -> LoginDialog(
            onDismiss = finishActivity,
            onConfirm = { account->
                dialogToShow = "loading"
                loginNetwork(account) { success, msg ->
                    if (success) {
                        confirmNetwork()
                        finishActivity()
                    } else {
                        message = msg
                        dialogToShow = "message"
                    }
                }
            },
            uiState = uiState,
            onSetAutoLogin = { it -> saveNetworkSetting(NetworkSetting(
                autoLogin = it,
                defaultAccountId = uiState.networkSetting.defaultAccountId
            ))},
            onAccountSelected = onAccountSelected
        )
        "unsupported" -> UnsupportedNetworkDialog(
            onDismiss = { finishActivity() },
            onSelectOtherApp = {
                val chooser = Intent.createChooser(intent, strings.selectOtherApp)
                context.startActivity(chooser)
                finishActivity()
            },
            onContinue = { dialogToShow = "login"},
        )
        "message" ->
            AlertDialog(
                onDismissRequest = { dialogToShow = "login" },
                confirmButton = { TextButton(onClick = { dialogToShow = "login" }) {Text(strings.confirm)} },
                text = { Text(message) }
            )
        "loading" ->
            Dialog(
                onDismissRequest = { /* 不允许外部点击关闭 */ },
            ) {
                Card(
                    modifier = Modifier.sizeIn(
                        minWidth = 280.dp,
                        maxWidth = 560.dp,
                    )
                ) {
                    Column(
                        horizontalAlignment = Alignment.CenterHorizontally,
                        modifier = Modifier.padding(16.dp)
                            .fillMaxWidth()
                    ) {
                        CircularProgressIndicator()
                    }
                }
            }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun LoginDialog(
    onDismiss: () -> Unit,
    onConfirm: (Account) -> Unit,
    uiState: NetworkConfigUiState,
    onSetAutoLogin: (Boolean) -> Unit = {},
    onAccountSelected: (String) -> Unit = {}
) {
    val strings = LocalStrings.current
    var selectedAccountId by remember { mutableStateOf(uiState.networkSetting.defaultAccountId) }

    if (uiState.allAccounts.isEmpty()){
        AlertDialog(
            onDismissRequest = onDismiss,
            title = { Text(strings.noAvailableAccount) },
            confirmButton = { TextButton(onClick = onDismiss) { Text(strings.cancel) } }
        )
    } else {
        AlertDialog(
            onDismissRequest = onDismiss,
            title = { Text(strings.loginTitle) },
            text = {
                Column {
                    AccountSelector(
                        uiState = uiState,
                        onAccountSelected = { onAccountSelected(it); selectedAccountId = it },
                        displayCreateNewAccount = false)
                    Spacer(modifier = Modifier.height(8.dp))
                    Row(
                        verticalAlignment = Alignment.CenterVertically,
                        modifier = Modifier.padding(vertical = 8.dp)
                    ) {
                        Text(strings.autoLogin, modifier = Modifier.weight(1f))
                        Switch(checked = uiState.networkSetting.autoLogin, onCheckedChange = onSetAutoLogin)
                    }
                }
            },
            confirmButton = {
                Button(onClick = { uiState.selectedAccount?.let{ onConfirm(it) } }) {
                    Text(strings.ok)
                }
            },
            dismissButton = {
                TextButton(onClick = onDismiss) {
                    Text(strings.cancel)
                }
            }
        )
    }
}

@Composable
private fun UnsupportedNetworkDialog(
    onDismiss: () -> Unit,
    onSelectOtherApp: () -> Unit,
    onContinue: () -> Unit,
) {
    val strings = LocalStrings.current

    AlertDialog(
        onDismissRequest = onDismiss,
        title = { Text(strings.unsupportedNetworkTitle) },
        text = { Text(strings.unsupportedNetworkMessage) },
        confirmButton = {
            Button(onClick = onSelectOtherApp ) {
                Text(strings.selectOtherApp)
            }
        },
//        dismissButton = {
//            TextButton(onClick = onContinue) {
//                Text(strings.continueWithThisApp)
//            }
//        }
    )
}

@RequiresPermission(Manifest.permission.ACCESS_NETWORK_STATE)
private fun getCurrentSsid(context: Context): String? {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val ssid = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)?.transportInfo?.toString()?.replace("\"", "")
    Log.info("ssid: $ssid")
    return ssid
}

@Preview
@Composable
fun PreviewCaptivePortalUi() {
    val fakeUiState = NetworkConfigUiState(
        allAccounts = listOf(
            Account(id = "1", username = "user1-preview", operator = Operator.CHINA_MOBILE, password = "123"),
            Account(id = "2", username = "user2-preview", operator = Operator.CHINA_TELECOM, password = "abc")
        ),
        selectedAccountId = "1", // Show the first account by default in preview
        isLoading = false,
        networkSetting = NetworkSetting(
            null, false
        )
    )
    CaptivePortalLoginUi(
        uiState = fakeUiState
    )
}